import {
    JsonController,
    Get, Post,
    Body,
    CurrentUser,
    Authorized,
    HeaderParam,
    UnauthorizedError,
    BodyParam,
    Patch,
    NotFoundError,
    Put
} from "routing-controllers";
import { User, UserModel } from "../entities/User";
import { AppDataSource } from "../database";
import { sign } from "jsonwebtoken";

const { APP_AUTH, APP_SECRET } = process.env;

@JsonController("/user")
export class UserController {
    private userRepository = AppDataSource.getRepository(User);

    @Get("/:id")
    @Authorized()
    async findOneBy(@CurrentUser() data: UserModel) {
        const user = await this.userRepository.findOneBy({ id: data.id });
        if (user) {
            return user;
        } else {
            throw new NotFoundError();
        }
    }

    @Put()
    @Authorized()
    async update(
        @BodyParam("name", { required: true }) name: string,
        @BodyParam("avatar", { required: true }) avatar: string,
        @CurrentUser() data: UserModel
    ) {
        const user = await this.userRepository.findOneBy({ id: data.id });
        if (user) {
            await this.userRepository.update(user.id, { name, avatar });
            return { message: "updated success" };
        } else {
            throw new NotFoundError();
        }
    }

    @Post("/auth/session")
    async signIn(
        @HeaderParam("app-auth", { required: true }) appAuth: string,
        @Body() data: UserModel
    ) {
        if (APP_AUTH !== appAuth) {
            throw new UnauthorizedError("no permission");
        }
        let user = await this.userRepository.findOneBy({ id: data.id });
        if (!user) {
            user = await this.userRepository.save({ ...data });
        }
        const token = sign({ ...user }, `${APP_SECRET}`, { expiresIn: "1d" })
        const refreshToken = sign({ ...user }, `${APP_SECRET}`, { expiresIn: "7d" })
        return { user, token, refreshToken };
    }

    @Get("/auth/session")
    @Authorized()
    getSession(@CurrentUser() user: UserModel) {
        return user;
    }
}
